#include "scon_file.h"

namespace SCon {

File* File::Create(const std::string& path, int creationMode, std::string* errorMessage) {
#ifdef __SCON_DEBUG__
#define _D_Create_ 1
#else
#define _D_Create_ 0
#endif

	File* cp = new File(path, creationMode);
	int accessMode = cp->CalculateAccessMode(creationMode);
	int openMode = cp->CalculateOpenMode(creationMode);
	int sharedMode = cp->CalculateSharedMode(creationMode);
	cp->fileDescriptor_ = CreateFileA(path.c_str(), accessMode, sharedMode, 0, openMode, FILE_ATTRIBUTE_NORMAL, 0);
	if (cp->fileDescriptor_ == INVALID_HANDLE_VALUE && errorMessage != 0) {
		int errorCode = GetLastError();
		//HLOCAL buf = NULL;
		char buf[500];
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,
						MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
						buf, 500, NULL);
		*errorMessage = buf;

		if (_D_Create_) {
			std::cout << "errorMessage: " << *errorMessage << "\n";
		}/* end of if */

	}/* end of if */

	if (cp->fileDescriptor_ == INVALID_HANDLE_VALUE) {
		delete cp;
		return 0;
	}/* end of if */

	return cp;
}//end of File* File::Create()

bool File::Close(File* cp, std::string* errorMessage) {
#ifdef __SCON_DEBUG__
#define _D_Close_ 1
#else
#define _D_Close_ 0
#endif
	if (cp == 0 || cp->fileDescriptor_ == 0) {
		return true;
	}/* end of if */

	bool noError = CloseHandle(cp->fileDescriptor_);
	if (!noError && errorMessage != 0) {
		int errorCode = GetLastError();
		char buf[500];
		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode,
						MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
						buf, 500, NULL);
		*errorMessage = buf;

		if (_D_Close_) {
			std::cout << "errorMessage: " << *errorMessage << "\n";
		}/* end of if */
	}/* end of if */

	delete cp;
	return noError;
}//end of bool File::Close()

bool File::CheckParameter(int creationMode, std::string* errorMessage) {
#ifdef __SCON_DEBUG__
#define _D_CheckParameter_ 1
#else
#define _D_CheckParameter_ 0
#endif

	bool parameterIsNotBad = true;
	if (creationMode < 9 || creationMode > 120) {
		parameterIsNotBad = false;
		if (errorMessage != 0) {
			*errorMessage = "Parameter out of range";
		}/* end of if */

		return parameterIsNotBad;
	}/* end of if */

	if (_D_CheckParameter_) {
		std::cout << "creationMode: " << std::hex << creationMode << "\n";
	}/* end of if */


	if (((creationMode & (CREATE | RECREATE | OPEN)) == (CREATE | OPEN)) ||
		((creationMode & (CREATE | OPEN)) == (CREATE | OPEN)) ||
		((creationMode & (CREATE | RECREATE)) == (CREATE | RECREATE)) ||
		(((creationMode & (OPEN | RECREATE)) == (OPEN | RECREATE)))) {
		
		if (_D_CheckParameter_) {
			std::cout << "This is creationMode: " << std::hex << creationMode << "\n";
		}/* end of if */

		parameterIsNotBad = false;
		if (errorMessage != 0) {
			*errorMessage = "Flags CREATE, OPEN and RECREATE can not be specified together";
		}/* end of if */

		return parameterIsNotBad;
	}/* end of if */

	if (((((creationMode & CREATE) == 0) &&
		((creationMode & OPEN) == 0) &&
		((creationMode & RECREATE) == 0)) == 0) ||
		((((creationMode & READ) == 0) &&
		((creationMode & WRITE) == 0)) == 0)) {

		if (_D_CheckParameter_) {
			std::cout << "And this is creationMode: " << std::hex << creationMode << "\n";
		}/* end of if */

		parameterIsNotBad = false;
		if (errorMessage != 0) {
			*errorMessage = "Creation mode and access mode can be specified";
		}/* end of if */

		return parameterIsNotBad;
	}/* end of if */

	return parameterIsNotBad;
}//end of bool File::CheckParameter()

int File::CalculateSharedMode(int creationMode) {
	int sharedMode = 0;
	if (creationMode & SHARED_READ) {
		sharedMode |= FILE_SHARE_READ;
	}/* end of if */

	if (creationMode & SHARED_WRITE) {
		sharedMode |= FILE_SHARE_WRITE;
	}/* end of if */

	return sharedMode;
}//end of int File::CalculateSharedMode()

int File::CalculateOpenMode(int creationMode) {
	int openMode = 0;
	if (creationMode & RECREATE) {
		return CREATE_ALWAYS;
	}/* end of if */

	if (creationMode & CREATE) {
		return CREATE_NEW;
	}/* end of if */

	if (creationMode & OPEN) {
		return OPEN_EXISTING;
	}/* end of if */

	return openMode;
}//end of int File::CalculateOpenMode()

int File::CalculateAccessMode(int creationMode) {
	int accessMode = 0;
	if (creationMode & READ) {
		accessMode |= GENERIC_READ;
	}/* end of if */

	if (creationMode & WRITE) {
		accessMode |= GENERIC_WRITE;
	}/* end of if */

	return accessMode;
}//end of int File::CalculateAccessMode()

} /* SCon  */ 
